<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>canvas例子效果</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      height: 100%;
      overflow: hidden;
    }
  </style>
</head>
<body>
  <canvas id="canvas"></canvas>
  <script>
    // 获取到画布对象
    var canvas = document.getElementById("canvas")
    var ctx = canvas.getContext("2d")
    // 调用方法设置画布的大小，且保证窗口变化时画布也要变化
    resize();
    window.onresize = resize;
    window.onpageshow = resize;
    
    // 该方法用于设置canvas画布的大小
    function resize() {
      canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
      canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    }

    var RAF = (function() {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
        window.setTimeout(callback, 1000 / 60);
      };
    })();

    // 鼠标活动时，获取鼠标的坐标
    var mouse_position = {x: null, y: null, max: 20000};
    window.onmousemove = function(e) {
      e = e || window.event;
      mouse_position.x = e.clientX;
      mouse_position.y = e.clientY;
    };
    window.onmouseout = function(e) {
      mouse_position.x = null;
      mouse_position.y = null;
    };

    // 添加粒子
    // x,y为粒子的坐标，ya,xa为粒子y,x方向的加速度，max为最大连线的距离
    var dots = [];
    for (var i = 0; i < 200; i++) {
      let x = Math.random()*canvas.width;
      let y = Math.random()*canvas.height;
      let xa = Math.random()*2 - 1;
      let ya = Math.random()*2 - 1;
      dots.push({
        x: x,
        y: y,
        xa: xa,
        ya: ya,
        max: 6000
      })
    }
    
    setTimeout(function() {
      animate();
    }, 100);

    // 每一帧的动画逻辑
    function animate() {
      // 清空整个画面的内容
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      // 将鼠标坐标添加进去，产生一个用于对比距离的点数组
      let ndots = [mouse_position].concat(dots);
      // 循环每一个粒子
      dots.forEach(function(dot) {
        // 给粒子的坐标按加速度进行变化
        dot.x += dot.xa;
        dot.y += dot.ya;
        // 遇到边框则加速度取反
        dot.xa *= (dot.x > canvas.width || dot.x < 0) ? -1 : 1;
        dot.ya *= (dot.y > canvas.height || dot.y < 0) ? -1 : 1;
        // 绘制小点
        ctx.fillRect(dot.x - 0.5, dot.y - 0.5, 1, 1);
        // 循环对比粒子间的距离,ndots是包含了鼠标信息的数组
        for (var i = 0; i < ndots.length; i++) {
          let d2 = ndots[i];
          if (dot === d2 || d2.x === null || d2.y === null) continue;
          let xc = dot.x - d2.x;
          let yc = dot.y - d2.y;
          // 两个粒子间的距离
          let dis = xc*xc + yc*yc;
          // 距离比，根据距离比来控制线的粗细
          let ratio;
          // 粒子间的距离小于dis时则生成一条线
          if (dis < d2.max) {
            // 如果该d2是鼠标的话，则让粒子向鼠标移动
            if (d2 === mouse_position && dis > (d2.max / 2)) {
              dot.x -= xc * 0.03;
              dot.y -= yc * 0.03;
            }
            // 计算距离比
            ratio = (d2.max - dis) / d2.max;
            // 画线，根据距离比控制线的粗细和颜色的浅淡
            ctx.beginPath();
            ctx.lineWidth = ratio /2;
            ctx.strokeStyle = 'rgba(0, 0, 0,' + (ratio + 0.2) + ')';
            ctx.moveTo(dot.x, dot.y);
            ctx.lineTo(d2.x, d2.y);
            ctx.stroke();
          }
        }
        // 将已经计算过的粒子从数组ndots删除
        ndots.splice(ndots.indexOf(dot), 1);
      });
      setTimeout(function(){animate()}, 10);
    }
  </script>
</body>
</html>